﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.Xml;
using System.Diagnostics;
using ElisaHippo.Properties;
using System.Security.AccessControl;

namespace ElisaHippo
{
    class Utility
    {
        static string sSaveFolder = "";
        static Configures configs;
        static readonly string cfgPath = "\\PathsConfig.xml";
        public static Configures Configures
        {
            get
            {
                if (configs == null)
                    configs = new Configures();
                     
                return configs;
            }
        }

        static public void WriteSelectionResult(string sRes)
        {
            if (!Directory.Exists(stringRes.EvoProcessFolder))
                Directory.CreateDirectory(stringRes.EvoProcessFolder);

            string sFile = stringRes.EvoProcessFolder + stringRes.selectionFolder;
            using (StreamWriter sw = new StreamWriter(sFile))
            {
                string sContent = string.Format("mode,0,{0}", sRes);
                sw.WriteLine(sContent);
            }


        }

        static private string CreateTestFolder()
        {
            string sFolder = GetSaveFolder() + stringRes.testFolder;
            Directory.CreateDirectory(sFolder);
            return sFolder;
        }

        static public string GetSaveFolder()
        {
            if (sSaveFolder != "")
                return sSaveFolder;
            if (configs == null)
                configs = new ElisaHippo.Configures();
            sSaveFolder = configs.SaveFolder;
            sSaveFolder += "\\" + DateTime.Now.ToString("yyyyMMdd");
            if (!Directory.Exists(sSaveFolder))
            {
                Directory.CreateDirectory(sSaveFolder);
            }

            sSaveFolder += "\\" + DateTime.Now.ToString("HHmmss");
            if (!Directory.Exists(sSaveFolder))
            {
                Directory.CreateDirectory(sSaveFolder);
            }
            return sSaveFolder+"\\";
        }

        static public string GetLayoutFolder()
        {
            string s = GetSaveFolder();
            s += "\\Layout\\";
            if (!Directory.Exists(s))
                Directory.CreateDirectory(s);
            return s;
        }

        static public string GetDataFolder()
        {
            string s = GetExeFolder() + stringRes.dataFolder;
            return s;
        }

        static public string GetExeFolder()
        {
            string s = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            return s;
        }

        static public string GetExcelPath()
        {
            //throw new NotImplementedException();
            string s = GetSaveFolder();
            s += "\\input.xls";
            return s;
        }  

        static public void CreateTestFiles(Dictionary<string,HashSet<string>> test_Barcodes )
        {
            string sTestFolder = CreateTestFolder();
            foreach (string sTest in test_Barcodes.Keys)
            {
                if (test_Barcodes[sTest].Count == 0)
                    continue;
             
                using (StreamWriter sw = new StreamWriter(sTestFolder + sTest + ".txt"))
                {
                    foreach (string sSampleID in test_Barcodes[sTest])
                    {
                        sw.WriteLine(sSampleID);
                    }
                }
            }

            bool bStillHaveItems = true;
            int perProcess = 88;
            int joblistIndex = 1;
            while (true)
            {
                bStillHaveItems = false;
                Dictionary<string, List<string>> test_BarcodesForThisJoblist = new Dictionary<string, List<string>>();

                foreach (string sTest in test_Barcodes.Keys)
                {
                    int num2Copy = (int)Math.Min(test_Barcodes[sTest].Count, perProcess);
                    if (num2Copy > 0)
                    {
                        string[] barcodes = new string[num2Copy];
                        test_Barcodes[sTest].CopyTo(barcodes, 0, num2Copy);
                        for (int i = 0; i < num2Copy; i++)
                            test_Barcodes[sTest].Remove(barcodes[i]);
                        test_BarcodesForThisJoblist.Add(sTest, barcodes.ToList());
                        bStillHaveItems = true;
                    }
                }

                if (bStillHaveItems)
                    GenerateWorkList(test_BarcodesForThisJoblist,joblistIndex);
                else
                    break;
                joblistIndex++;
            }
            using (StreamWriter sw = new StreamWriter(GetSaveFolder() + "\\joblists\\Count.txt"))
            {
                sw.WriteLine((joblistIndex-1).ToString());
            }

        }

       private static void CopyFolder(string sourceFolder, string destFolder)  
       {  
           if (!Directory.Exists(destFolder))  
           {  
                Directory.CreateDirectory(destFolder);  
            }  
            string[] files = Directory.GetFiles(sourceFolder);  
           foreach (string file in files)  
            {  
                string name = Path.GetFileName(file);  
  
                string dest = Path.Combine(destFolder, name);  
  
                File.Copy(file, dest,true);  
            }  
            string[] folders = Directory.GetDirectories(sourceFolder);  
            foreach (string folder in folders)  
            {  
                string name = Path.GetFileName(folder);  
  
                string dest = Path.Combine(destFolder, name);  
  
                CopyFolder(folder, dest);  
            }  
        }  


        public static void CopyDummyFolder(string sDstFolder)
        {
            string sDummyFolder = GetDataFolder() + stringRes.dummyFolder;
            CopyFolder(sDummyFolder, sDstFolder);
        }


        public static void Move2WorkingFolder()
        {
            string sWorkingFolder = GetDataFolder() + stringRes.workingFolder;
            if (!Directory.Exists(sWorkingFolder))
                Directory.CreateDirectory(sWorkingFolder);
            else
            {
                try
                {
                    DeleteDir(sWorkingFolder, true);
                }
                catch(Exception ex)
                {
                    MessageBox.Show("无法删除working文件夹,这很可能是由于EVOWare状态异常所致\r\n,请停止当前的任务并关闭EVOWare软件！");
                    throw new Exception("Failed to delete working folder.");
                   
                }
         
            }
            CopyFolder(GetSaveFolder(), sWorkingFolder);
        }

        private static bool CheckDeleteResult(string sWorkingFolder)
        {
            if (sWorkingFolder[sWorkingFolder.Length - 1] != Path.DirectorySeparatorChar)
                sWorkingFolder += Path.DirectorySeparatorChar;
            string[] fileList = Directory.GetFileSystemEntries(sWorkingFolder);
            return fileList.Length == 0;
        }

        
        public static void DeleteDir(string aimPath,bool bKeepCurrent)
        {
            if (!bKeepCurrent)
            {
                Directory.Delete(aimPath, true);
                return;
            }
            
            // 检查目标目录是否以目录分割字符结束如果不是则添加之
            if(aimPath[aimPath.Length-1] != Path.DirectorySeparatorChar) 
                    aimPath += Path.DirectorySeparatorChar;
            // 得到源目录的文件列表，该里面是包含文件以及目录路径的一个数组
            // 如果你指向Delete目标文件下面的文件而不包含目录请使用下面的方法
            // string[] fileList = Directory.GetFiles(aimPath);
            string[] fileList = Directory.GetFileSystemEntries(aimPath);
            // 遍历所有的文件和目录
            foreach(string file in fileList)
            {
                    // 先当作目录处理如果存在这个目录就递归Delete该目录下面的文件
                    if(Directory.Exists(file))
                    {
                        DeleteDir(aimPath+Path.GetFileName(file),false);
                    }
                    // 否则直接Delete文件
                    else
                    {
                        if (Path.GetFileName(file).IndexOf("barcodes.txt") != -1) //don't delete barcodes, it is needed by EVOware
                            continue;
                        File.Delete (aimPath+Path.GetFileName(file));
                    }
            }
        }


        private static void GenerateWorkList(Dictionary<string, List<string>> test_BarcodesForThisJoblist,int index)
        {
            string sPath = GetSaveFolder() + string.Format("\\joblists\\{0}\\",index) ;
            if( !Directory.Exists(sPath) )
                Directory.CreateDirectory(sPath);

            CopyDummyFolder(sPath);
            Dictionary<string, string> test_LimsID = ReadTest_LimsDict();

            using (StreamWriter sw = new StreamWriter(sPath+string.Format("joblist{0}.twl",index)))
            {
                sw.WriteLine("Start;");
                sw.WriteLine("V:1;");
                foreach (string sTest in test_BarcodesForThisJoblist.Keys)
                {
                    string sTestPath = sPath + sTest + ".txt";
                    
                    using (StreamWriter sw2 = new StreamWriter(sTestPath))
                    {
                        sw2.WriteLine(test_BarcodesForThisJoblist[sTest].Count);
                    }
                    foreach (string sBarcode in test_BarcodesForThisJoblist[sTest])
                    {
                        sw.WriteLine(string.Format("T:{0};;;{1}",sBarcode,test_LimsID[sTest]));
                    }
                }
                sw.WriteLine("End;");
            }
        }

        private static Dictionary<string, string> ReadTest_LimsDict()
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();
            string sPath = Utility.Configures.Test_LimsID_Dict;
            using (StreamReader sr = new StreamReader(sPath))
            {
                string s = "";
                while ((s = sr.ReadLine()) != null)
                {
                    string[] sRes = s.Split('\t');
                    dict.Add(sRes[1], sRes[0]);
                }
            }
            return dict;
        }

        static public void WriteExecuteResult(bool bok)
        {
            string sPath = GetSaveFolder() + stringRes.resFile;
            if (File.Exists(sPath))
            {
                try
                {
                    File.Delete(sPath);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
            }
            
            using (StreamWriter sw = new StreamWriter(sPath))
            {
                sw.WriteLine(bok.ToString());    
            }
        }
        public static string Serialize<T>(T value)
        {
            if (value == null)
            {
                return null;
            }

            XmlSerializer serializer = new XmlSerializer(typeof(T));
            XmlWriterSettings settings = new XmlWriterSettings();
            //settings.Encoding = new UnicodeEncoding(false, false);
            settings.Indent = true;
            //settings.OmitXmlDeclaration = false;

            using (StringWriter textWriter = new StringWriter())
            {
                using (XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings))
                {
                    serializer.Serialize(xmlWriter, value);
                }
                return textWriter.ToString();
            }
        }

        public static T Deserialize<T>(string xml)
        {
            if (string.IsNullOrEmpty(xml))
            {
                return default(T);
            }

            XmlSerializer serializer = new XmlSerializer(typeof(T));
            XmlReaderSettings settings = new XmlReaderSettings();

            using (StringReader textReader = new StringReader(xml))
            {
                using (XmlReader xmlReader = XmlReader.Create(textReader, settings))
                {
                    return (T)serializer.Deserialize(xmlReader);
                }
            }
        }
        static public void SaveSetting(DataGridView dataGridView, int sampleCount)
        {

            StreamWriter sw = new StreamWriter(Utility.GetExcelPath(), false, System.Text.Encoding.GetEncoding(-0));
            string strLine = "";

            //Write in the headers of the columns.  
            for (int i = 0; i < dataGridView.ColumnCount; i++)
            {
                if (i > 0)
                    strLine += Convert.ToChar(9);
                strLine += dataGridView.Columns[i].HeaderText;
            }
            strLine.Remove(strLine.Length - 1);
            sw.WriteLine(strLine);
            strLine = "";
            //Write in the content of the columns.  
            int lastColumnRows = sampleCount % 16;
            if (lastColumnRows == 0)
                lastColumnRows = 16;
            for (int j = 0; j < dataGridView.Rows.Count; j++)
            {
                strLine = "";
                for (int k = 0; k < dataGridView.Columns.Count; k++)
                {

                    if (k == dataGridView.Columns.Count - 1 && j >= lastColumnRows)
                        break;

                    if (k > 0)
                        strLine += Convert.ToChar(9);
                    if (dataGridView.Rows[j].Cells[k].Value == null)
                        strLine += "";
                    else
                    {
                        string m = dataGridView.Rows[j].Cells[k].Value.ToString().Trim();
                        strLine += m;
                    }
                }
                if (strLine != string.Empty)
                {
                    strLine.Remove(strLine.Length - 1);
                    sw.WriteLine(strLine);
                }
            }
            sw.Close();
        }
    }
}
